/*
* coder  : dzlua
* email  : 505544956@qq.com
* module : trans-server
* path   : src
* file   : main.cpp
* time   : 2018-01-24 13:13:57
*/

#include <evpp/tcp_server.h>
#include <evpp/event_loop_thread_pool.h>
#include <evpp/buffer.h>
#include <evpp/tcp_conn.h>

struct Data {
    int64_t time;
    std::string sublib;
    std::string title;
    std::string url;
    std::string type;
    std::string author;
    std::string from;
    std::string content;
    static std::shared_ptr<Data> parser(evpp::Buffer* msg) {
        auto data = std::make_shared<Data>();
        data->time = msg->ReadInt64();
        data->sublib = msg->NextString(msg->ReadInt64());
        data->title = msg->NextString(msg->ReadInt64());
        data->url = msg->NextString(msg->ReadInt64());
        data->type = msg->NextString(msg->ReadInt64());
        data->author = msg->NextString(msg->ReadInt64());
        data->from = msg->NextString(msg->ReadInt64());
        data->content = msg->NextString(msg->ReadInt64());
        return data;
    }
};

class Task {
public:
    Task() {}
    ~Task() {}
public:
    void start() {}
    void stop() {}
    void push(const std::shared_ptr<Data>& data) {
        LOG_INFO << "time:" << data->time;
        LOG_INFO << "sublib:" << data->sublib;
        LOG_INFO << "title:" << data->title;
        LOG_INFO << "url:" << data->url;
        LOG_INFO << "type:" << data->type;
        LOG_INFO << "author:" << data->author;
        LOG_INFO << "from:" << data->from;
        LOG_INFO << "content:" << data->content;
    }
    std::shared_ptr<Data> pop() {}
};

class Handle {
public:
    Handle() {}
    ~Handle() {}
public:
    void start(const std::string &addr, int thread_num) {
        task_ = std::shared_ptr<Task>();
        loop_ = std::make_shared<evpp::EventLoop>();
        tpool_ = std::make_shared<evpp::EventLoopThreadPool>(loop_.get(), thread_num);
        tpool_->Start(true);

        std::vector<std::shared_ptr<evpp::TCPServer>> tcp_servers;
        for (uint32_t i = 0; i < thread_num; i++) {
            evpp::EventLoop* next = tpool_->GetNextLoop();
            std::shared_ptr<evpp::TCPServer> s(new evpp::TCPServer(next, addr, std::to_string(i) + "#trans-server", 0));
            s->SetMessageCallback(this->_OnMessageCallback);
            s->SetConnectionCallback(this->_OnConnectionCallback);
            s->Init();
            s->Start();
            tcp_servers.push_back(s);
        }
        
        loop_->Run();
    }

    void stop() {}
protected:
    static void _OnMessageCallback(const evpp::TCPConnPtr& conn,
                evpp::Buffer* msg) {
        LOG_INFO << "id=" << conn->name() << " tid=" << std::this_thread::get_id() << " Received a message len=" << msg->size();
        auto data = Data::parser(msg);
        task_->push(data);
        conn->Send("done");
        msg->Reset();
    }
    static void _OnConnectionCallback(const evpp::TCPConnPtr& conn) {
        if (conn->IsConnected()) {
            LOG_INFO << "Connected to " << conn->remote_addr();
            conn->Send("done");
        } else {
            LOG_INFO << "Disconnected to " << conn->remote_addr();
            conn->loop()->Stop();
        }
    }
private:
    static std::shared_ptr<evpp::EventLoop> loop_;
    static std::shared_ptr<evpp::EventLoopThreadPool> tpool_;
    static std::shared_ptr<Task> task_;
};

std::shared_ptr<Task> Handle::task_ = nullptr;
std::shared_ptr<evpp::EventLoop> Handle::loop_ = nullptr;
std::shared_ptr<evpp::EventLoopThreadPool> Handle::tpool_ = nullptr;

int main(int argc, char* argv[]) {
    std::string addr = "0.0.0.0:9099";
    uint32_t thread_num = 2;

    if (argc != 3) {
        printf("Usage: %s <port> <thread-num>\n", argv[0]);
        printf("  e.g: %s 9099 12\n", argv[0]);
        return 0;
    }

    if (argc == 3) {
        addr = std::string("0.0.0.0:") + argv[1];
        thread_num = atoi(argv[2]);
    }

    Handle handle;
    handle.start(addr, thread_num);
    handle.stop();
    
    return 0;
}

#ifdef WIN32
#include "winmain-inl.h"
#endif
